/*
 * Copyright (c) 2020-2021 imlzw@vip.qq.com jweb.cc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cc.jweb.adai.web.system.generator.service;

import cc.jweb.adai.web.WebApplication;
import cc.jweb.boot.http.NetUtils;
import cc.jweb.boot.utils.lang.StringUtils;
import cc.jweb.boot.utils.lang.SystemUtils;
import com.jfinal.kit.PathKit;
import cc.jweb.adai.web.websocket.service.LogWebSocketService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;

public class WebServerService {
    private final static Logger logger = LoggerFactory.getLogger(WebServerService.class);

    private final static ConcurrentHashMap<Integer, Process> webServerCache = new ConcurrentHashMap();

    public static int getCurrJwebPid() {
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        String name = runtime.getName(); // format: "pid@hostname"
        try {
            return Integer.parseInt(name.substring(0, name.indexOf('@')));
        } catch (Exception e) {
            return -1;
        }
    }

    public static boolean checkJwebPidExist(String pid) {
        boolean isExist = false;
        ProcessBuilder pb = null;
        if (SystemUtils.isWindows()) {
            pb = new ProcessBuilder("tasklist");
        } else if (SystemUtils.isLinux()) {
            pb = new ProcessBuilder("ps -ef | grep java");
        }
        pb.redirectErrorStream(true);
        //启动进程
        try {
            Process process = pb.start();
            InputStream is = process.getInputStream();
            InputStreamReader isr = null;
            try {
                isr = new InputStreamReader(is, "gbk");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            BufferedReader br = new BufferedReader(isr);
            try {
                String content = br.readLine();
                while (content != null) {
                    content = br.readLine();
                    if (content != null && content.indexOf("java") >= 0 && content.indexOf(pid) >= 0) {
                        isExist = true;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return isExist;
    }


//    public static void main(String[] args) {
//        System.out.println(checkJwebPidExist(14856));
//    }

    /**
     * 启动Jweb Web服务
     *
     * @param extClassPath
     * @param debug
     * @throws Exception
     */
    public static int startWebWithJwebBoot(String extClassPath, String workDir, Boolean debug) throws Exception {
        int port = NetUtils.getAvailablePort();
        int debugPort = NetUtils.getAvailablePort();
        Process process = webServerCache.get(port);
        if (process == null || !process.isAlive()) {
            try {
                String debugParam = " -Dfile.encoding=utf-8 -Xdebug -Djweb.ppid=" + getCurrJwebPid() + "  -Xrunjdwp:transport=dt_socket,server=y,suspend=" + (Boolean.TRUE.equals(debug) ? "y" : "n") + ",address=" + debugPort + " ";
                String portParam = " -Dundertow.port=" + port + " ";
                // web资源路径
                String[] resourcesPaths = new String[]{
                        extClassPath + File.separator + "webapp",
                        PathKit.getRootClassPath() + File.separator + "webapp",
                        PathKit.getWebRootPath() + File.separator + "webapp",
                        "src/main/webapp",
                        "target/classes/webapp",
                        "classpath:webapp",
                        // 如果是开发环境
                        (new File(PathKit.getRootClassPath()).getParentFile().getParentFile().getAbsolutePath()) + "/src/main/webapp"
                };
                String resourcePathParam = " -Dtest=true -Dundertow.resourcePath=\"" + StringUtils.join(resourcesPaths, ",") + "\" ";
                String cmd = "java " + debugParam + portParam + resourcePathParam + CodeGenerator.getTestWebClassPathParams(extClassPath) + WebApplication.class.getName();
                LogWebSocketService.sendMessage("启动命令：" + cmd);
                process = Runtime.getRuntime().exec(cmd, null, new File(workDir));
                Process finalProcess1 = process;
                // 虚拟机退出时，销毁子进程
                Runtime.getRuntime().addShutdownHook(new Thread(() -> finalProcess1.destroy()));
                webServerCache.put(port, process);
            } catch (IOException e) {
                logger.error("调用启动web程序异常！", e);
                LogWebSocketService.sendError(e);
            }
            Process finalProcess = process;
            new Thread(() -> {
                InputStream is = finalProcess.getInputStream();
                InputStreamReader isr = null;
                try {
                    isr = new InputStreamReader(is, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                BufferedReader br = new BufferedReader(isr);
                try {
                    String content = br.readLine();
                    while (content != null) {
                        System.out.println(content);
                        LogWebSocketService.sendMessage("1>：" + content);
                        content = br.readLine();
                    }
                } catch (IOException e) {
                    LogWebSocketService.sendMessage("1>：" + e.getMessage());
                }
            }).start();
            new Thread(() -> {
                InputStream is = finalProcess.getErrorStream();
                InputStreamReader isr = null;
                try {
                    isr = new InputStreamReader(is, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                BufferedReader br = new BufferedReader(isr);
                try {
                    String content = br.readLine();
                    while (content != null) {
                        System.out.println(content);
                        LogWebSocketService.sendMessage("2>：" + content);
                        content = br.readLine();
                    }
                } catch (IOException e) {
                    LogWebSocketService.sendMessage("2>：" + e.getMessage());
                }
            }).start();
        } else {
            throw new Exception("当前已存在端口为" + port + "的Web服务，无法启动新的Web服务！");
        }
        return port;
    }

    /**
     * 启动Jetty Web 服务
     *
     * @param webappDir
     * @param extClassPath
     * @return
     * @throws Exception
     */
    public static int startWebWithJetty(String webappDir, String extClassPath, String workDir) throws Exception {
        int port = NetUtils.getAvailablePort();
        Process process = webServerCache.get(port);
        if (process == null || !process.isAlive()) {
            try {
                String debug = " -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=3999 ";
                String cmd = "java " + debug + CodeGenerator.getTestWebClassPathParams(extClassPath) + " cc.jweb.adai.web.generator.service.WebServerService" + "  " + port + " " + webappDir;
                process = Runtime.getRuntime().exec(cmd, null, new File(workDir));
                webServerCache.put(port, process);
            } catch (IOException e) {
                logger.error("调用启动web程序异常！", e);
                LogWebSocketService.sendError(e);
            }
            Process finalProcess = process;
            new Thread(() -> {
                InputStream is = finalProcess.getInputStream();
                InputStreamReader isr = null;
                try {
                    isr = new InputStreamReader(is, "gbk");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                BufferedReader br = new BufferedReader(isr);
                try {
                    String content = br.readLine();
                    while (content != null) {
                        System.out.println(content);
                        LogWebSocketService.sendMessage("1>：" + content);
                        content = br.readLine();
                    }
                } catch (IOException e) {
                    LogWebSocketService.sendMessage("1>：" + e.getMessage());
                }
            }).start();
            new Thread(() -> {
                InputStream is = finalProcess.getErrorStream();
                InputStreamReader isr = null;
                try {
                    isr = new InputStreamReader(is, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                BufferedReader br = new BufferedReader(isr);
                try {
                    String content = br.readLine();
                    while (content != null) {
                        System.out.println(content);
                        LogWebSocketService.sendMessage("2>：" + content);
                        content = br.readLine();
                    }
                } catch (IOException e) {
                    LogWebSocketService.sendMessage("2>：" + e.getMessage());
                }
            }).start();
        } else {
            throw new Exception("当前已存在端口为" + port + "的Web服务，无法启动新的Web服务！");
        }
        return port;
    }

    /**
     * 停止指定端口的Web服务
     *
     * @param port
     * @throws Exception
     */
    public static void stopWeb(int port) throws Exception {
        if (port == -1) {
            for (Integer pt : new HashSet<Integer>(webServerCache.keySet())) {
                Process process = webServerCache.get(pt);
                if (process != null) {
                    process.destroyForcibly();
                    process = null;
                    webServerCache.remove(pt);
                }
            }
        } else {
            Process process = webServerCache.get(port);
            if (process != null) {
                process.destroyForcibly();
                process = null;
                webServerCache.remove(port);
            }
        }
    }

    public static boolean hasStartedWeb(int port) {
        if (port == -1) {
            return !webServerCache.isEmpty();
        }
        Process process = webServerCache.get(port);
        return process != null && process.isAlive();
    }

    public static void startWithJetty(int port, String webroot, String extClassPath) throws Exception {
//        Server server = new Server(port);
//        WebAppContext context = new WebAppContext();
//        context.setAttribute("test", true);
//        context.setContextPath("/");
//        context.setResourceBase(webroot);// 指定webapp目录
//        context.setExtraClasspath(extClassPath);
//        context.setClassLoader(ClassLoader.getSystemClassLoader());
//        server.setHandler(context);
//        server.start();
//        server.join();
    }

}
